package com.ssy.lingxi.marketing.serviceimpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.marketing.entity.activity.MerchantActivityDO;
import com.ssy.lingxi.marketing.entity.activity.PlatformActivityDO;
import com.ssy.lingxi.marketing.entity.coupon.MerchantCouponDO;
import com.ssy.lingxi.marketing.entity.coupon.PlatformCouponDO;
import com.ssy.lingxi.marketing.model.constant.*;
import com.ssy.lingxi.marketing.repository.*;
import com.ssy.lingxi.marketing.service.IMarketingScheduleCallBackService;
import com.ssy.lingxi.marketing.service.IPlatformActivityService;
import com.ssy.lingxi.marketing.service.IProcessFeignService;
import com.ssy.lingxi.scheduler.api.model.ScheduleTaskCallbackVO;
import com.ssy.lingxi.workflow.api.model.contant.ProcessTaskStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 平台、商家活动定时服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/8/25
 */
@Slf4j
@Service
public class MarketingScheduleCallBackServiceImpl implements IMarketingScheduleCallBackService {

    @Resource
    private PlatformActivityRepository platformActivityRepository;
    @Resource
    private IProcessFeignService processFeignService;
    @Resource
    private PlatformActivitySignUpRepository signUpRepository;
    @Resource
    private MerchantActivityRepository merchantActivityRepository;
    @Resource
    private IPlatformActivityService platformActivityService;
    @Resource
    private PlatformCouponRepository platformCouponRepository;
    @Resource
    private MerchantCouponRepository merchantCouponRepository;

    @Override
    public void startPfActivitySignUpTask(ScheduleTaskCallbackVO callbackVO) {
        Long activityId = this.getSingleDataId(callbackVO);
        if (Objects.isNull(activityId)) {
            log.error("定时任务回调, 报名时间开始, dataId为空");
            return;
        }

        // 查询平台活动
        PlatformActivityDO platformActivityDO = platformActivityRepository.findById(activityId).orElse(null);
        if (Objects.isNull(platformActivityDO)) {
            log.error("定时任务回调, 报名时间开始, 未找到平台活动信息, activityId: {}", activityId);
            return;
        }

        // 活动参与类型为商家报名
        if (!ActivitySignUpTypeEnum.SUPPLIER.getCode().equals(platformActivityDO.getActivitySignUpType())) {
            log.error("定时任务回调, 报名时间开始, 活动参与类型有误, activityId: {}, activitySingUpType: {}", platformActivityDO.getId(), platformActivityDO.getActivitySignUpType());
            return;
        }

        // 状态要为待报名
        if (!PlatformActivityOuterStatusEnum.TO_BE_SIGN_UP.getCode().equals(platformActivityDO.getOuterStatus())) {
            log.error("定时任务回调, 报名时间开始, 外部状态有误, activityId: {}, outerStatus: {}", platformActivityDO.getId(), platformActivityDO.getOuterStatus());
            return;
        }

        Map<String, Object> taskAttributes = callbackVO.getTaskAttributes();
        Long executeTime = (Long) taskAttributes.get(TaskTypeEnum.Constants.EXECUTE_TIME);

        // 判断执行时间
        if (platformActivityDO.getSignUpStartTime().compareTo(executeTime) != 0) {
            log.error("定时任务回调, 报名时间开始, 执行时间有误, 可能已被修改, activityId: {}, signUpStartTime: {}", platformActivityDO.getId(), platformActivityDO.getSignUpStartTime());
            return;
        }

        // 报名时间开始前一分钟容错允许, 当前时间 >= (报名开始时间 - 1min)
        int minute = 60 * 1000;
        long currentTimeMillis = System.currentTimeMillis();

        if (currentTimeMillis >= (platformActivityDO.getSignUpStartTime() - minute) && currentTimeMillis < platformActivityDO.getSignUpEndTime()) {
            platformActivityDO = processFeignService.completeSimpleTaskByPlatformActivityOuter(platformActivityDO, ProcessTaskStatusEnum.GOTO_NEXT_STEP.getCode());
            platformActivityDO.setInnerStatus(PlatformActivityInnerStatusEnum.TO_BE_EXAMINE_SIGN_UP.getCode());
            platformActivityRepository.saveAndFlush(platformActivityDO);
        } else {
            throw new BusinessException(ResponseCode.MARKETING_PLATFORM_ACTIVITY_IS_NOT_SIGN_UP_TIME);
        }
    }

    @Override
    public void endPfActivitySignUpTask(ScheduleTaskCallbackVO callbackVO) {
        Long activityId = this.getSingleDataId(callbackVO);
        if (Objects.isNull(activityId)) {
            log.error("定时任务回调, 报名时间结束, dataId为空");
            return;
        }

        // 查询平台活动
        PlatformActivityDO platformActivityDO = platformActivityRepository.findById(activityId).orElse(null);
        if (Objects.isNull(platformActivityDO)) {
            log.error("定时任务回调, 报名时间结束, 未找到平台活动信息, activityId: {}", activityId);
            return;
        }

        // 活动参与类型为商家报名
        if (!ActivitySignUpTypeEnum.SUPPLIER.getCode().equals(platformActivityDO.getActivitySignUpType())) {
            log.error("定时任务回调, 报名时间结束, 活动参与类型有误, activityId: {}, activitySingUpType: {}", platformActivityDO.getId(), platformActivityDO.getActivitySignUpType());
            return;
        }

        // 状态要为待审核报名
        if (!PlatformActivityOuterStatusEnum.TO_BE_EXAMINE_SIGN_UP.getCode().equals(platformActivityDO.getOuterStatus())) {
            log.error("定时任务回调, 报名时间结束, 活动外部状态有误, activityId: {}, outerStatus: {}", platformActivityDO.getId(), platformActivityDO.getOuterStatus());
            return;
        }

        if (System.currentTimeMillis() < platformActivityDO.getSignUpEndTime()) {
            log.error("定时任务回调, 报名时间结束, 当前时间小于报名结束时间, activityId: {}, signUpEndTime: {}", platformActivityDO.getId(), platformActivityDO.getSignUpEndTime());
            return;
        }

        Map<String, Object> taskAttributes = callbackVO.getTaskAttributes();
        // 经过一轮序列化到数据库和反序列化出来, 其真实类型是linkedHashMap
        Object loginUserObj = taskAttributes.get(TaskTypeEnum.Constants.PLATFORM_USER);
        UserLoginCacheDTO loginUser = BeanUtil.toBean(loginUserObj, UserLoginCacheDTO.class);
        Long executeTime = (Long) taskAttributes.get(TaskTypeEnum.Constants.EXECUTE_TIME);

        // 判断执行时间
        if (platformActivityDO.getSignUpEndTime().compareTo(executeTime) != 0) {
            log.error("定时任务回调, 报名时间结束, 执行时间有误, 可能已被修改, activityId: {}, signUpEndTime: {}", platformActivityDO.getId(), platformActivityDO.getSignUpEndTime());
            return;
        }

        // 报名时间结束, 需要平台处理完所有商家提交的报名资料, 才能进入下个流程
        platformActivityService.updateByAllSignUp(loginUser, platformActivityDO);
    }

    @Override
    public void endPfActivityTask(ScheduleTaskCallbackVO callbackVO) {
        Long activityId = this.getSingleDataId(callbackVO);
        if (Objects.isNull(activityId)) {
            log.error("定时任务回调, 平台活动时间结束, dataId为空");
            return;
        }

        // 查询平台活动
        PlatformActivityDO platformActivityDO = platformActivityRepository.findById(activityId).orElse(null);
        if (Objects.isNull(platformActivityDO)) {
            log.error("定时任务回调, 平台活动时间结束, 未找到平台活动信息, activityId: {}", activityId);
            return;
        }

        // 如果已经结束，则返回
        if (PlatformActivityOuterStatusEnum.END.getCode().equals(platformActivityDO.getOuterStatus())) {
            log.error("定时任务回调, 平台活动时间结束, 外部状态已结束, activityId: {}, outerStatus: {}", platformActivityDO.getId(), platformActivityDO.getOuterStatus());
            return;
        }

        Map<String, Object> taskAttributes = callbackVO.getTaskAttributes();
        Long executeTime = (Long) taskAttributes.get(TaskTypeEnum.Constants.EXECUTE_TIME);

        // 判断执行时间
        if (platformActivityDO.getEndTime().compareTo(executeTime) != 0) {
            log.error("定时任务回调, 平台活动时间结束, 执行时间有误, 可能已被修改, activityId: {}, endTime: {}", platformActivityDO.getId(), platformActivityDO.getEndTime());
            return;
        }

        // 活动结束
        platformActivityDO.setOuterStatus(PlatformActivityOuterStatusEnum.END.getCode());
        platformActivityDO.setInnerStatus(PlatformActivityInnerStatusEnum.END.getCode());
        platformActivityRepository.saveAndFlush(platformActivityDO);
    }

    @Override
    public void endMcActivityTask(ScheduleTaskCallbackVO callbackVO) {
        Long activityId = this.getSingleDataId(callbackVO);
        if (Objects.isNull(activityId)) {
            log.error("定时任务回调, 商家活动时间结束, dataId为空");
            return;
        }

        // 查询商家活动
        MerchantActivityDO merchantActivityDO = merchantActivityRepository.findById(activityId).orElse(null);
        if (Objects.isNull(merchantActivityDO)) {
            log.error("定时任务回调, 商家活动时间结束, 未找到商家活动信息, activityId: {}", activityId);
            return;
        }

        // 如果已经结束，则返回
        if (MerchantActivityInnerStatusEnum.END.getCode().equals(merchantActivityDO.getInnerStatus())) {
            log.error("定时任务回调, 商家活动时间结束, 内部状态已结束, activityId: {}, innerStatus: {}", merchantActivityDO.getId(), merchantActivityDO.getInnerStatus());
            return;
        }

        Map<String, Object> taskAttributes = callbackVO.getTaskAttributes();
        Long executeTime = (Long) taskAttributes.get(TaskTypeEnum.Constants.EXECUTE_TIME);

        // 判断执行时间
        if (merchantActivityDO.getEndTime().compareTo(executeTime) != 0) {
            log.error("定时任务回调, 商家活动时间结束, 执行时间有误, 可能已被修改, activityId: {}, endTime: {}", merchantActivityDO.getId(), merchantActivityDO.getEndTime());
            return;
        }

        // 活动结束
        //22.1.20版废弃 merchantActivityDO.setOuterStatus(MerchantActivityOuterStatusEnum.END.getCode());
        merchantActivityDO.setInnerStatus(MerchantActivityInnerStatusEnum.END.getCode());
        merchantActivityRepository.saveAndFlush(merchantActivityDO);
    }

    @Override
    public void startPfCouponReleaseTask(ScheduleTaskCallbackVO callbackVO) {
        Long couponId = this.getSingleDataId(callbackVO);
        if (Objects.isNull(couponId)) {
            log.error("定时任务回调, 平台优惠券发放开始, dataId为空");
            return;
        }

        // 查询平台优惠券
        PlatformCouponDO platformCouponDO = platformCouponRepository.findById(couponId).orElse(null);
        if (Objects.isNull(platformCouponDO)) {
            log.error("定时任务回调, 平台优惠券发放开始, 未找到平台优惠券信息, couponId: {}", couponId);
            return;
        }

        // 如果已经开始，则返回
        if (PlatformCouponStatusEnum.EXECUTING.getCode().equals(platformCouponDO.getStatus())) {
            log.error("定时任务回调, 平台优惠券发放开始, 状态已开始, couponId: {}, status: {}", platformCouponDO.getId(), platformCouponDO.getStatus());
            return;
        }

        Map<String, Object> taskAttributes = callbackVO.getTaskAttributes();
        Long executeTime = (Long) taskAttributes.get(TaskTypeEnum.Constants.EXECUTE_TIME);

        // 判断执行时间
        if (platformCouponDO.getReleaseTimeStart().compareTo(executeTime) != 0) {
            log.error("定时任务回调, 平台优惠券发放开始, 执行时间有误, 可能已被修改, couponId: {}, releaseTimeStart: {}", platformCouponDO.getId(), platformCouponDO.getReleaseTimeStart());
            return;
        }

        platformCouponDO.setStatus(PlatformCouponStatusEnum.EXECUTING.getCode());
        platformCouponRepository.saveAndFlush(platformCouponDO);
    }

    @Override
    public void endPfCouponReleaseTask(ScheduleTaskCallbackVO callbackVO) {
        Long couponId = this.getSingleDataId(callbackVO);
        if (Objects.isNull(couponId)) {
            log.error("定时任务回调, 平台优惠券发放结束, dataId为空");
            return;
        }

        // 查询平台优惠券
        PlatformCouponDO platformCouponDO = platformCouponRepository.findById(couponId).orElse(null);
        if (Objects.isNull(platformCouponDO)) {
            log.error("定时任务回调, 平台优惠券发放结束, 未找到平台优惠券信息, couponId: {}", couponId);
            return;
        }

        // 如果已经结束，则返回
        if (PlatformCouponStatusEnum.FINISH.getCode().equals(platformCouponDO.getStatus())) {
            log.error("定时任务回调, 平台优惠券发放结束, 状态已结束, couponId: {}, status: {}", platformCouponDO.getId(), platformCouponDO.getStatus());
            return;
        }

        Map<String, Object> taskAttributes = callbackVO.getTaskAttributes();
        Long executeTime = (Long) taskAttributes.get(TaskTypeEnum.Constants.EXECUTE_TIME);

        // 判断执行时间
        if (platformCouponDO.getReleaseTimeEnd().compareTo(executeTime) != 0) {
            log.error("定时任务回调, 平台优惠券发放结束, 执行时间有误, 可能已被修改, couponId: {}, releaseTimeEnd: {}", platformCouponDO.getId(), platformCouponDO.getReleaseTimeEnd());
            return;
        }

        platformCouponDO.setStatus(PlatformCouponStatusEnum.FINISH.getCode());
        platformCouponRepository.saveAndFlush(platformCouponDO);
    }

    @Override
    public void startMcCouponReleaseTask(ScheduleTaskCallbackVO callbackVO) {
        Long couponId = this.getSingleDataId(callbackVO);
        if (Objects.isNull(couponId)) {
            log.error("定时任务回调, 商家优惠券发放开始, dataId为空");
            return;
        }

        // 查询平台优惠券
        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(couponId).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            log.error("定时任务回调, 商家优惠券发放开始, 未找到商家优惠券信息, couponId: {}", couponId);
            return;
        }

        // 如果已经开始，则返回
        if (MerchantCouponStatusEnum.EXECUTING.getCode().equals(merchantCouponDO.getStatus())) {
            log.error("定时任务回调, 商家优惠券发放开始, 状态已开始, couponId: {}, status: {}", merchantCouponDO.getId(), merchantCouponDO.getStatus());
            return;
        }

        Map<String, Object> taskAttributes = callbackVO.getTaskAttributes();
        Long executeTime = (Long) taskAttributes.get(TaskTypeEnum.Constants.EXECUTE_TIME);

        // 判断执行时间
        if (merchantCouponDO.getReleaseTimeStart().compareTo(executeTime) != 0) {
            log.error("定时任务回调, 商家优惠券发放开始, 执行时间有误, 可能已被修改, couponId: {}, releaseTimeStart: {}", merchantCouponDO.getId(), merchantCouponDO.getReleaseTimeStart());
            return;
        }

        merchantCouponDO.setStatus(MerchantCouponStatusEnum.EXECUTING.getCode());
        merchantCouponRepository.saveAndFlush(merchantCouponDO);
    }

    @Override
    public void endMcCouponReleaseTask(ScheduleTaskCallbackVO callbackVO) {
        Long couponId = this.getSingleDataId(callbackVO);
        if (Objects.isNull(couponId)) {
            log.error("定时任务回调, 商家优惠券发放结束, dataId为空");
            return;
        }

        // 查询平台优惠券
        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(couponId).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            log.error("定时任务回调, 商家优惠券发放结束, 未找到商家优惠券信息, couponId: {}", couponId);
            return;
        }

        // 如果已经结束，则返回
        if (MerchantCouponStatusEnum.FINISH.getCode().equals(merchantCouponDO.getStatus())) {
            log.error("定时任务回调, 商家优惠券发放结束, 状态已结束, couponId: {}, status: {}", merchantCouponDO.getId(), merchantCouponDO.getStatus());
            return;
        }

        Map<String, Object> taskAttributes = callbackVO.getTaskAttributes();
        Long executeTime = (Long) taskAttributes.get(TaskTypeEnum.Constants.EXECUTE_TIME);

        // 判断执行时间
        if (merchantCouponDO.getReleaseTimeEnd().compareTo(executeTime) != 0) {
            log.error("定时任务回调, 商家优惠券发放结束, 执行时间有误, 可能已被修改, couponId: {}, releaseTimeEnd: {}", merchantCouponDO.getId(), merchantCouponDO.getReleaseTimeEnd());
            return;
        }

        merchantCouponDO.setStatus(MerchantCouponStatusEnum.FINISH.getCode());
        merchantCouponRepository.saveAndFlush(merchantCouponDO);
    }

    private Long getSingleDataId(ScheduleTaskCallbackVO callbackVO) {
        List<Long> idList = callbackVO.getDataIds();
        if (CollectionUtil.isEmpty(idList)) {
            return null;
        }

        return idList.get(0);
    }
}
